//////////////////////////////////////
// Fast Container Library           //
// MIT License - Copyright (c) 2012 //
//////////////////////////////////////

#pragma once

#include "common.h"
#include "type_traits.h"


FC_NAMESPACE_BEGIN


template<class T1, class T2>
struct pair
{
	typedef T1 first_type;
	typedef T2 second_type;

	pair() : first(), second() {}
	pair( const first_type& a ) : first(a), second() {}
	pair( const first_type& a, const second_type& b ) : first(a), second(b) {}

	template <typename U, typename V>
	pair( const pair<U, V>& p ) : first(p.first), second(p.second) {}

	T1	first;
	T2	second;
};


template<class T1, class T2> inline
	bool operator ==( const pair<T1, T2>& a, const pair<T1, T2>& b )
	{
		return a.first == b.first && a.second == b.second;
	}

template<class T1, class T2, class U, class V> inline
	bool operator ==( const pair<T1, T2>& a, const pair<U, V>& b )
	{
		return a.first == b.first && a.second == b.second;
	}

template<class T1, class T2> inline
	bool operator !=( const pair<T1, T2>& a, const pair<T1, T2>& b )
	{
		return !(a == b);
	}

template<class T1, class T2, class U, class V> inline
	bool operator !=( const pair<T1, T2>& a, const pair<U, V>& b )
	{
		return !(a == b);
	}


// make_pair

template<class T1, class T2>
	pair<T1, T2> make_pair( const T1& a, const T2& b )
	{
		return pair<T1, T2>(a, b);
	}


// key_pair_comparer

template <class Key, class Value, class Compare>
struct key_pair_comparer
{
	typedef Key						first_argument_type;
	typedef Value					second_argument_type;
	typedef Compare					compare_type;
	typedef pair<Key, Value>		pair_type;

	key_pair_comparer( const Compare& c = Compare() )
		: compare(c) {}

	inline bool operator()( const pair_type& lhs, const pair_type& x ) const { return compare(lhs.first, x.first); }
	inline bool operator()( const pair_type& lhs, const Key& x ) const { return compare(lhs.first, x); }
	inline bool operator()( const Key& lhs, const pair_type& x ) const { return compare(lhs, x.first); }
	inline bool operator()( const Key& lhs, const Key& x ) const { return compare(lhs, x); }

	Compare compare;
};



// Types of pair are considered trivial only if both templated types are trivial.

template <class T1, class T2> struct is_pod< pair<T1, T2> > : integral_constant
	<bool, (is_pod<T1>::value && is_pod<T2>::value)> { };

template <class T1, class T2> struct has_trivial_constructor< pair<T1, T2> > : integral_constant
	<bool, (has_trivial_constructor<T1>::value && has_trivial_constructor<T2>::value)> { };

template <class T1, class T2> struct has_trivial_copy< pair<T1, T2> > : integral_constant
	<bool, (has_trivial_copy<T1>::value && has_trivial_copy<T2>::value)> { };

template <class T1, class T2> struct has_trivial_assign< pair<T1, T2> > : integral_constant
	<bool, (has_trivial_assign<T1>::value && has_trivial_assign<T2>::value)> { };


namespace rel_ops
{
	template <class T> inline bool operator!=( const T& a, const T& b ) { return !(a == b); }
	template <class T> inline bool operator >( const T& a, const T& b ) { return (b < a); }
	template <class T> inline bool operator<=( const T& a, const T& b ) { return !(b < a); }
	template <class T> inline bool operator>=( const T& a, const T& b ) { return !(a < b); }
}


FC_NAMESPACE_END
